package com.snow.datasource.creator;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;
import com.snow.datasource.properties.DataSourceProperty;
import com.snow.datasource.creator.druid.DruidProperties;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.StringUtils;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * 阿里巴巴druid数据源创建
 *
 * @Description
 * @Author fanxl
 * @Date 2020/12/17
 **/
@Slf4j
public class DruidCreator implements IDataSourceCreator, ApplicationContextAware {

    private final static String DRUID_DATA_SOURCE = "com.alibaba.druid.pool.DruidDataSource";

    @Setter
    @Getter
    private DruidProperties druid;

    private ApplicationContext applicationContext;

    static {
        try {
            Class.forName(DRUID_DATA_SOURCE);
        } catch (ClassNotFoundException ignored) {
            log.info("创建DruidDataSource失败{}", ignored.getMessage());
        }
    }

    public DruidCreator(DruidProperties druidProperties){
        this.druid = druidProperties;
    }
    @Override
    public DataSource createDataSource(DataSourceProperty property) {
        log.info("create DruidDataSource:{}",property.getUrl());
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(property.getUrl());
        dataSource.setUsername(property.getUsername());
        dataSource.setPassword(property.getPassword());
        String driverClassName = property.getDriverClassName();
        if (!StringUtils.isEmpty(driverClassName)) {
            dataSource.setDriverClassName(driverClassName);
        }
        if (ObjectUtil.isNotNull(druid.getKeepAlive())) {
            dataSource.setKeepAlive(druid.getKeepAlive());
        }
        if (ObjectUtil.isNotNull(druid.getAsyncInit())) {
            dataSource.setAsyncInit(druid.getAsyncInit());
        }
        if (ObjectUtil.isNotNull(druid.getMinIdle())) {
            dataSource.setMinIdle(druid.getMinIdle());
        }
        if (ObjectUtil.isNotNull(druid.getMaxActive())) {
            dataSource.setMaxActive(druid.getMaxActive());
        }
        if (ObjectUtil.isNotNull(druid.getMaxWait())) {
            dataSource.setMaxWait(druid.getMaxWait());
        }
        if (ObjectUtil.isNotNull(druid.getInitialSize())) {
            dataSource.setInitialSize(druid.getInitialSize());
        }
        if (ObjectUtil.isNotNull(druid.getTimeBetweenEvictionRunsMillis())) {
            dataSource.setTimeBetweenEvictionRunsMillis(druid.getTimeBetweenEvictionRunsMillis());
        }
        if (ObjectUtil.isNotNull(druid.getTimeBetweenEvictionRunsMillis())) {
            dataSource.setTimeBetweenConnectErrorMillis(druid.getTimeBetweenEvictionRunsMillis());
        }
        if (ObjectUtil.isNotNull(druid.getTimeBetweenLogStatsMillis())) {
            dataSource.setTimeBetweenLogStatsMillis(druid.getTimeBetweenLogStatsMillis());
        }
        if (StrUtil.isNotEmpty(druid.getValidationQuery())) {
            dataSource.setValidationQuery(druid.getValidationQuery());
        }
        if (ObjectUtil.isNotNull(druid.getTestWhileIdle())) {
            dataSource.setTestWhileIdle(druid.getTestWhileIdle());
        }
        if (ObjectUtil.isNotNull(druid.getTestOnBorrow())) {
            dataSource.setTestOnBorrow(druid.getTestOnBorrow());
        }
        if (ObjectUtil.isNotNull(druid.getTestOnReturn())) {
            dataSource.setTestOnReturn(druid.getTestOnReturn());
        }

        DruidProperties config = property.getDruid();
        Properties properties = DruidProperties.toProperties(druid);
        String filters = properties.getProperty("druid.filters");
        List<Filter> proxyFilters = new ArrayList<>(2);
        if (!StringUtils.isEmpty(filters) && filters.contains("stat")) {
            StatFilter statFilter = new StatFilter();
            statFilter.configFromProperties(properties);
            proxyFilters.add(statFilter);
        }
        dataSource.setProxyFilters(proxyFilters);
        dataSource.configFromPropety(properties);

        try {
            dataSource.init();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return dataSource;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
